package co.baiku.boot.common.spring;

import co.baiku.boot.common.tools.AnnotationTools;
import co.baiku.boot.common.tools.ObjectTools;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScans;

import java.lang.annotation.Annotation;
import java.util.*;

public class SpringBootInfo {
    public static final SpringBootInfo ME = new SpringBootInfo();

    private Set<String> scanPackages = new HashSet<>();

    private SpringBootInfo() {

    }

    /**
     * 全局扫描包汇总
     */
    public void loadScanPackages() {
        List<ComponentScan> scans = new ArrayList<>();
        Map<String, Object> componentScanBeanMap = SpringContext.getBeansWithAnnotation(ComponentScan.class);
        if (ObjectTools.isNotBlank(componentScanBeanMap)) {
            componentScanBeanMap.forEach((k, v) -> {
                Annotation classAnnotation = AnnotationTools.findClassAnnotation(v.getClass(), ComponentScan.class);
                if (classAnnotation != null) {
                    scans.add((ComponentScan) classAnnotation);
                }
            });
        }

        Map<String, Object> componentScanBeansMap = SpringContext.getBeansWithAnnotation(ComponentScans.class);
        if (ObjectTools.isNotBlank(componentScanBeansMap)) {
            componentScanBeansMap.forEach((k, v) -> {
                Annotation classAnnotation = AnnotationTools.findClassAnnotation(v.getClass(), ComponentScans.class);
                if (classAnnotation != null) {
                    scans.addAll(Arrays.asList(((ComponentScans) classAnnotation).value()));
                }
            });
        }
        for (ComponentScan scan : scans) {
            if (scan == null || scan.basePackages().length == 0) {
                continue;
            }
            scanPackages.addAll(Arrays.asList(scan.basePackages()));
        }

        Map<String, Object> springBootApplicationMap = SpringContext.getBeansWithAnnotation(SpringBootApplication.class);
        if (ObjectTools.isNotBlank(springBootApplicationMap)) {
            springBootApplicationMap.forEach((k, v) -> {
                Annotation classAnnotation = AnnotationTools.findClassAnnotation(v.getClass(), SpringBootApplication.class);
                if (classAnnotation != null && ((SpringBootApplication) classAnnotation).scanBasePackages().length > 0) {
                    scanPackages.addAll(Arrays.asList(((SpringBootApplication) classAnnotation).scanBasePackages()));
                }
            });
        }

        //其他模块扫描包上报
        Map<String, SpringBootInfoTentacle> springBootInfoTentacleMap = SpringContext.getBeansOfType(SpringBootInfoTentacle.class);
        springBootInfoTentacleMap.forEach((k, v) -> scanPackages.addAll(v.getScanPackages()));
    }

    public Set<String> getScanPackages() {
        if (this.scanPackages.isEmpty()) {
            loadScanPackages();
        }
        return scanPackages;
    }

}
